/*
 * This file is Copyright 2002-2006 Loyola University Chicago,
 * Department of Computer Science and the Emerging Technologies Laboratory.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License via
 *    http://www.apache.org/licenses/LICENSE-2.0.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.citep.web.admin.transactions.client;

import java.util.Date;

import com.citep.web.gwt.dto.HistoryEncoder;
import com.citep.web.gwt.module.Presentation;
import com.citep.web.gwt.module.BasePresentation;
import com.citep.web.gwt.validators.NumberValidator;
import com.citep.web.gwt.validators.RequiredValidator;
import com.citep.web.gwt.validators.ValidatorGroup;
import com.citep.web.gwt.widgets.DynaTable;
import com.citep.web.gwt.widgets.Shortcut;
import com.citep.web.gwt.widgets.ShortcutTable;
import com.citep.web.gwt.widgets.CalendarEntry;
import com.citep.web.gwt.widgets.StatusLabel;

import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;

public class TransactionEntryPresentation extends BasePresentation implements Presentation {

	protected TransactionEntryApplication application;
	
	protected VerticalPanel mainPanel;
	protected VerticalPanel context;
	
	protected ShortcutTable shortcuts;
	protected FlexTable inputTable;
	
	protected TextBox memoText;
	protected TextBox amountText;
	protected ListBox transactionType = new ListBox();
	protected ListBox destinationAccount = new ListBox();
	protected CalendarEntry transactionDate;
	protected Button submitButton;
	protected ClickListener saveAction;

	protected StatusLabel statusLabel;
	protected Button editAccountButton;
	
	//this is where we show entries for this account
	protected DynaTable entryTable;
	
	protected ValidatorGroup validator;

	public TransactionEntryPresentation() {
		setTitle("New Transaction");
		shortcuts = new ShortcutTable("Accounts",10);
		shortcuts.setMoreLink(new Hyperlink("[more]","__account_list__"));
	}

	
	public void setApplication(TransactionEntryApplication application) {
		this.application = application;
	}

	public void addShortcut(Shortcut shortcut, boolean highlight) {
		shortcuts.addShortcut(shortcut, highlight);
	}
	
	public void updateShortcut(Shortcut shortcut, boolean highlight) {
		shortcuts.updateShortcut(shortcut, highlight);
	}	

	public void clearShortcuts() {
		shortcuts.clearEntries();
	}
	

	public void addAccountToSelect(String accountName) {
		destinationAccount.addItem(accountName);
	}
	
	public void clearAccountSelection() {
		destinationAccount.clear();
	}

	public void addEntryType(String entryType) {
		transactionType.addItem(entryType);
	}
	
	public void clearEntryTypes() {
		transactionType.clear();
	}
	
	public void setTitle(String title) {
		getTitleLabel().setText(title);
		getEditAccountButton().setVisible(true);
	}
		
	public void displayStatus(String msg, int seconds) {
		getStatusLabel().setText(msg);
		getStatusLabel().show(seconds);
	}
	
	public void setLoadingState() {
		getStatusLabel().setText("Loading...");
		getStatusLabel().setVisible(true);
		getEditAccountButton().setEnabled(false);
		getSubmitButton().setEnabled(false);
	}
	
	public void setReadyState() {
		getStatusLabel().hide();
		getEditAccountButton().setEnabled(true);
		getSubmitButton().setEnabled(true);
	}
	
	public void setSavingState() {
		getStatusLabel().setText("Saving...");
		getStatusLabel().setVisible(true);		
		getEditAccountButton().setEnabled(false);
		getSubmitButton().setEnabled(false);
	}

	public Widget getContext() {
		if(context == null) {
			context = new VerticalPanel();
			context.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
			context.setStyleName("context_table");
			context.setSpacing(0);
	
			context.add(shortcuts);
			
			Button importButton = new Button("Import");
			importButton.setStyleName("form_button");
			importButton.addClickListener(new ClickListener() {
				public void onClick(Widget w) {
					String token = HistoryEncoder.encode("transactions_import", null);
					History.newItem(token);					
				}
			});
			
			context.add(importButton);
		}
		
		return context;
	}

	public Widget getMainPanel() {
		if(mainPanel == null) {
			mainPanel = new VerticalPanel();
			mainPanel.setWidth("100%");
			//mainPanel.add(getTitleLabel());
			getTitlePanel().setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
			getTitlePanel().add(getStatusLabel());
			
			getTitlePanel().setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
			getTitlePanel().add(getEditAccountButton());
			mainPanel.add(getTitlePanel());
			
			mainPanel.add(getInputTable());
			mainPanel.add(getSubmitButton());
			mainPanel.setCellHorizontalAlignment(getSubmitButton(), HasHorizontalAlignment.ALIGN_CENTER);
			
			mainPanel.setCellHorizontalAlignment(getStatusLabel(), HasHorizontalAlignment.ALIGN_CENTER);
			
			mainPanel.add(getEntryTable());
			mainPanel.setCellHorizontalAlignment(getEntryTable(), HasHorizontalAlignment.ALIGN_CENTER);
		}
		
		return mainPanel;
	}

	private void addWidgetToInputGrid(FlexTable g, int rowIdx,int colIdx,String description, Widget w) {
		g.setText(rowIdx, colIdx, description);
		g.setWidget(rowIdx,colIdx+1, w);
		g.getCellFormatter().setStyleName(rowIdx, colIdx, "input_cell");
		g.getCellFormatter().setStyleName(rowIdx, colIdx+1, "input_cell");
	}
	

	private void setValidation() {
		if(validator == null)
			validator = new ValidatorGroup();
		
		ValidationErrorListener listener = new ValidationErrorListener();
		
		validator.addValidator("Entry.account", destinationAccount, new RequiredValidator(listener, "Please select an account"));
		validator.addValidator("Transaction.transactionTime", getTransactionDate().getTextBox(), new RequiredValidator(listener, "Please select a transaction date"));
		validator.addValidator("Entry.type",transactionType,new RequiredValidator(listener,"Please select a valid transaction type"));
		validator.addValidator("Entry.amount",amountText,new RequiredValidator(listener, "Please enter an amount"));
		validator.addValidator("Entry.amount", amountText, new NumberValidator(listener,"Please enter a valid number"));
	}
	
	
	private FlexTable getInputTable() {
		if(inputTable == null) {
			inputTable = new FlexTable();
			inputTable.setCellPadding(0);
			inputTable.setCellSpacing(0);
			
			inputTable.setStyleName("input_grid");
			


			addValidationLabelToGrid(inputTable,0,1,createErrorLabel("Entry.account"));
			
			addWidgetToInputGrid(inputTable,1,0,"From account:",destinationAccount);
			
			addWidgetToInputGrid(inputTable,1,2,"Date:",getTransactionDate());
			
			
			addValidationLabelToGrid(inputTable,0,3,createErrorLabel("Transaction.transactionTime"));
			
			inputTable.getCellFormatter().setWidth(1, 2, "40%");
			inputTable.getCellFormatter().setWidth(1, 1, "40%");
			inputTable.getCellFormatter().setHorizontalAlignment(1, 2, HasHorizontalAlignment.ALIGN_RIGHT);
			
			addValidationLabelToGrid(inputTable,2,1,createErrorLabel("Entry.type"));

			addWidgetToInputGrid(inputTable,3,0,"Do a:",transactionType);
			
			amountText = createTextBox("form_textentry",10);
			addWidgetToInputGrid(inputTable,3,2,"Amount:",amountText);
			
			addValidationLabelToGrid(inputTable,2,3,createErrorLabel("Entry.amount"));
			
			inputTable.getCellFormatter().setWidth(3, 2, "40%");
			inputTable.getCellFormatter().setWidth(3, 1, "40%");
			inputTable.getCellFormatter().setHorizontalAlignment(3, 2, HasHorizontalAlignment.ALIGN_RIGHT);
			
			memoText = createTextBox("form_textentry",40);
			addWidgetToInputGrid(inputTable,4,0,"Memo:",memoText);
			
			inputTable.getFlexCellFormatter().setColSpan(4, 1, 3);
			
			setValidation();
		}
		

		return inputTable;
	}	
	
	private CalendarEntry getTransactionDate() {
		if(transactionDate == null) {
			transactionDate = new CalendarEntry("img/icon-calendar.png");
			transactionDate.setStyleName("calendar_entry");
			
		}
		return transactionDate;
	}

	private StatusLabel getStatusLabel() {
		if(statusLabel == null) {
			statusLabel = new StatusLabel();
			statusLabel.setStyleName("status_label_small");
			statusLabel.setText("text");
			statusLabel.hide();
		}

		return statusLabel;
	}
	
	protected Button getSubmitButton() {
		if(submitButton == null) {
			submitButton = new Button("Save");
			submitButton.setStyleName("form_big_button");
			
			submitButton.addClickListener(getSaveAction());
		}
		return submitButton;
	}
	
	protected Button getEditAccountButton() {
		if(editAccountButton == null) {
			editAccountButton = new Button("Edit Account");
			editAccountButton.setVisible(false);
			editAccountButton.addClickListener(new ClickListener() {
				public void onClick(Widget w) {
					application.launchEditAccount();
				}
			});
		}
		return editAccountButton;
	}
	
	private ClickListener getSaveAction() {
		if(saveAction == null) {
			saveAction = new ClickListener() {
				public void onClick(Widget w) {
					clearErrors();
					if(validator.validate()) {
						application.addTransaction(destinationAccount.getItemText(destinationAccount.getSelectedIndex()), 
								transactionType.getItemText(transactionType.getSelectedIndex()), 
								memoText.getText(), 
								new Date(transactionDate.getTextBox().getText()), 
								amountText.getText());
					}
				};
			};
		}
		return saveAction;
	}	

	private void addValidationLabelToGrid(FlexTable g, int row, int col, HTML label) {
		g.setWidget(row,col, label);
		g.getCellFormatter().setStyleName(row, 1, "error_label");
		g.getRowFormatter().setStyleName(row, "hidden");
	}

	private DynaTable getEntryTable() {
		if(entryTable == null) {
			entryTable = new DynaTable(application,  new String [] {"Date", "Memo", "Account", "Debit", "Credit","Balance"}, "data_grid", "data_grid_header", "data_grid_entry", new String [] {"grid_normal_item", "grid_small_item","grid_small_item","grid_small_item", "grid_small_item","grid_normal_item"}, 10);
			entryTable.setWidth("80%");
			
		}
		
		return entryTable;
	}
	
	public void refreshTransactions() {
		getEntryTable().refresh();
	}
	
}
